/**
 * Copyright (c) 2016-2019 九点科技 All rights reserved.
 *
 * http://www.9dyun.cn
 *
 * 版权所有，侵权必究！
 */
package com.dian.modules.inv.service.impl;

import com.alibaba.fastjson.JSON;
import com.dian.common.exception.RRException;
import com.dian.common.utils.*;
import com.dian.common.validator.ValidatorUtils;
import com.dian.common.validator.group.AddGroup;
import com.dian.modules.base.entity.GoodsEntity;
import com.dian.modules.base.entity.WarehouseEntity;
import com.dian.modules.base.service.GoodsService;
import com.dian.modules.base.service.WarehouseService;
import com.dian.modules.base.service.impl.BaseConfigServiceImpl;
import com.dian.modules.common.dto.ConverDto;
import com.dian.modules.common.server.BusService;
import com.dian.modules.inv.entity.GoodsAccountEntity;
import com.dian.modules.inv.poi.vo.GoodsStockInitExportVO;
import com.dian.modules.inv.service.GoodsAccountService;
import com.dian.modules.inv.service.InLineService;
import com.dian.modules.inv.service.OutLineService;
import com.dian.modules.inv.vo.GoodsStockVO;
import com.dian.modules.sale.service.OrderHeadService;
import com.dian.modules.sale.service.ProbHeadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.apache.commons.collections.CollectionUtils;
import cn.hutool.core.util.StrUtil;

import java.math.BigDecimal;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dian.common.server.CommonService;
import com.dian.modules.inv.dao.GoodsStockDao;
import com.dian.modules.inv.entity.GoodsStockEntity;
import com.dian.modules.inv.service.GoodsStockService;
import com.dian.modules.inv.poi.vo.GoodsStockExportVO;

/**
 * 库存表服务实现类
 *
 * @author xiaolai
 * @email xiaolai@9dyun.cn
 * @date 2019-06-29 15:53:12
 */
@Service("goodsStockService")
public class GoodsStockServiceImpl extends ServiceImpl<GoodsStockDao, GoodsStockEntity> implements GoodsStockService {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    public CommonService commonService;

    @Autowired
    public GoodsService goodsService;


    @Autowired
    public BusService busService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private GoodsAccountService goodsAccountService;


    @Autowired
    private BaseConfigServiceImpl baseConfigService;

    @Autowired
    public InLineService inLineService;

    @Autowired
    public OutLineService outLineService;

    @Autowired
    public ProbHeadService probHeadService;

    @Autowired
    public OrderHeadService orderHeadService;

    /**
     * 库存表分页
     * @param params
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<GoodsStockEntity> page = this.page(new Query<GoodsStockEntity>().getPage(params),getQueryWrapper(params) );
        converPageList(page);
        return new PageUtils(page);
    }




    /**
     *库存表当前页or全部导出
     * @param params
     * @return
     */
    @Override
    public List<GoodsStockExportVO> exportList(Map<String, Object> params) {
        List<GoodsStockEntity> list;
        if(!StrUtil.isBlankIfStr(params.get("exprotType"))){
            list= this.page(new Query<GoodsStockEntity>().getPage(params),getQueryWrapper(params)).getRecords();
        }else{
            list= this.list(getQueryWrapper(params));
        }

        List<GoodsStockExportVO> resultList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(list)) {
            resultList = BeanConverter.convertList(list, GoodsStockExportVO.class);
        }
        return resultList;
    }

    /**
     * 库存表导出
     * @param params
     * @return
     */
    @Override
    public List<GoodsStockInitExportVO> initExport(Map<String, Object> params){
        List<Map<String,Object>> list= this.baseMapper.initExport();
        List<GoodsStockInitExportVO> resultList = new ArrayList<>();
        String settleMonth=baseConfigService.getValue("SettleMonth");
        if(CollectionUtils.isNotEmpty(list)) {
            resultList = BeanConverter.convertList(list, GoodsStockInitExportVO.class);
            ListUtils.setPropertyValue(resultList,"year",new Date().toYearText());
            ListUtils.setPropertyValue(resultList,"month",settleMonth);
        }

        return resultList;
    }

    /**
     * 库存表导入
     * @param list
     * @return
     */
    @Override
    public void initImport( List<GoodsStockInitExportVO> list){
        if(CollectionUtils.isNotEmpty(list)){
            list.forEach(importVo -> {
                WarehouseEntity warehouseEntity=warehouseService.queryByCode(importVo.getWarehouseCode());
                GoodsEntity goodsEntity=goodsService.queryByCode(importVo.getGoodsCode());
                /*stockEntity.setGoodsId(goodsEntity.getId());
                stockEntity.setGoodsCode(goodsEntity.getGoodsCode());
                stockEntity.setGoodsName(goodsEntity.getGoodsName());
                stockEntity.setGoodsSpec(goodsEntity.getGoodsSpec());
                stockEntity.setItemGrade(goodsEntity.getItemGrade());
                stockEntity.setColorNumber(goodsEntity.getColorNumber());*/
                GoodsStockEntity stockEntity=BeanConverter.convert(goodsEntity,GoodsStockEntity.class);

                stockEntity.setWarehouseId(warehouseEntity.getId());
                stockEntity.setWarehouseCode(warehouseEntity.getWarehouseCode());
                stockEntity.setWarehouseName(warehouseEntity.getWarehouseName());
                stockEntity.setGoodsId(goodsEntity.getId());
                ConverDto converDto=busService.convert(new ConverDto(BigDecimal.ZERO,importVo.getQtyNum(),importVo.getAuxNum(),goodsEntity.getConverUnit1(),goodsEntity.getConverUnit2()));

                stockEntity.setBaseNum(converDto.getBaseNum());
                stockEntity.setAuxNum(converDto.getAuxNum());
                stockEntity.setQtyNum(converDto.getQtyNum());

                //设置可用库存
                stockEntity.setAvaBaseNum(converDto.getBaseNum());
                stockEntity.setAvaQtyNum(converDto.getQtyNum());
                stockEntity.setAvaAuxNum(converDto.getAuxNum());
                this.save(stockEntity);


                //String settleMonth=baseConfigService.getValue("SettleMonth");
                GoodsAccountEntity goodsAccountEntity=BeanConverter.convert(goodsEntity,GoodsAccountEntity.class);
                goodsAccountEntity.setGoodsId(goodsEntity.getId());
                goodsAccountEntity.setBeginAmount(converDto.getQtyNum());
                goodsAccountEntity.setBeginAuxNum(converDto.getAuxNum());
                goodsAccountEntity.setBeginQtyNum(converDto.getQtyNum());
                goodsAccountEntity.setBeginBaseNum(converDto.getBaseNum());


                //设置期初实际可用数量
                goodsAccountEntity.setBeginAvaAuxNum(converDto.getAuxNum());
                goodsAccountEntity.setBeginAvaQtyNum(converDto.getQtyNum());
                goodsAccountEntity.setBeginAvaBaseNum(converDto.getBaseNum());



                goodsAccountEntity.setBeginPrice(importVo.getPrice());
                goodsAccountEntity.setBeginAmount(importVo.getPrice().multiply(converDto.getBaseNum()));
                goodsAccountEntity.setAccountYear(importVo.getYear());
                goodsAccountEntity.setAccountMonth(importVo.getMonth());
                goodsAccountEntity.setWarehouseId(warehouseEntity.getId());
                goodsAccountEntity.setWarehouseCode(warehouseEntity.getWarehouseCode());
                goodsAccountEntity.setWarehouseName(warehouseEntity.getWarehouseName());
                 goodsAccountService.initBeginAccount(goodsAccountEntity);
            });
        }
    }

    /**
     * 查询商品库存
     * @param goodsStockVO
     * @return
     */
    @Override
    public GoodsStockEntity queryStockInfo(GoodsStockVO goodsStockVO){
        if(goodsStockVO==null)  throw new RRException(String.format("参数错误"));
        //校验输入参数是否完整
        ValidatorUtils.validateEntity(goodsStockVO, AddGroup.class);

        QueryWrapper<GoodsStockEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("goods_id", goodsStockVO.getGoodsId());
        queryWrapper.eq("warehouse_id", goodsStockVO.getWarehouseId());
        queryWrapper.eq(StrUtil.isNotBlank(goodsStockVO.getColorNumber()),"color_number",goodsStockVO.getColorNumber() );
        queryWrapper.eq(goodsStockVO.getItemGrade()!=null,"item_grade",goodsStockVO.getItemGrade() );
        return this.getOne(queryWrapper);


    }

    /**
     * 扣减可用库存(动态条件必须能确定唯一库存记录)
     *
     * @param stockVO
     * @return
     */
    @Override
    public boolean casReduceStock(GoodsStockVO stockVO){
        //查询当前商品的库存数
        // 上月结存+入库-出库
        GoodsStockVO goodsSumStockVO= this.queryIncreaseStock(stockVO,false);
        GoodsStockEntity goodsStockEntity= this.queryStockInfo(stockVO);
        if(goodsStockEntity!=null){
            goodsStockEntity.setAvaBaseNum(goodsSumStockVO.getAvaBaseNum());
            goodsStockEntity.setAvaQtyNum(goodsSumStockVO.getAvaQtyNum());
            goodsStockEntity.setAvaAuxNum(goodsSumStockVO.getAvaAuxNum());
            this.updateById(goodsStockEntity);
        }else{
            throw new RRException(String.format("%s 在 %s 无有效可用库存",stockVO.getGoodsCode(),stockVO.getWarehouseCode()));
        }
        return true;
    }

    /**
     * 增加可用库(仅增加可用库存)
     *
     * @param stockVO
     * @return
     */
    @Override
    public boolean casIncreaseStock(GoodsStockVO stockVO){
        //
        GoodsStockVO goodsSumStockVO= this.queryIncreaseStock(stockVO,true);
        GoodsStockEntity goodsStockEntity= this.queryStockInfo(stockVO);
        if(goodsStockEntity!=null){
            goodsStockEntity.setAvaBaseNum(goodsSumStockVO.getAvaBaseNum());
            goodsStockEntity.setAvaQtyNum(goodsSumStockVO.getAvaQtyNum());
            goodsStockEntity.setAvaAuxNum(goodsSumStockVO.getAvaAuxNum());
            this.updateById(goodsStockEntity);
        }else{
            GoodsEntity goodsEntity=goodsService.getById(stockVO.getGoodsId());
            goodsStockEntity=BeanConverter.convert(goodsEntity,GoodsStockEntity.class);
            goodsStockEntity.setAvaBaseNum(goodsSumStockVO.getAvaBaseNum());
            goodsStockEntity.setAvaQtyNum(goodsSumStockVO.getAvaQtyNum());
            goodsStockEntity.setAvaAuxNum(goodsSumStockVO.getAvaAuxNum());

            this.save(goodsStockEntity);
        }
        return true;
    }

    /**
     * 扣减实际库存(可用库存和实际库存同时扣减）
     * @return
     */
    public  boolean casReduceActualStock(GoodsStockVO stockVO){
        GoodsStockVO goodsSumStockVO= this.queryIncreaseStock(stockVO,false);
        GoodsStockEntity goodsStockEntity= this.queryStockInfo(stockVO);
        if(goodsStockEntity!=null){
            goodsStockEntity.setBaseNum(goodsSumStockVO.getBaseNum());
            goodsStockEntity.setQtyNum(goodsSumStockVO.getQtyNum());
            goodsStockEntity.setAuxNum(goodsSumStockVO.getAuxNum());
            this.updateById(goodsStockEntity);
        }else{
            throw new RRException(String.format("%s 在 %s 无有效实际库存",stockVO.getGoodsCode(),stockVO.getWarehouseCode()));
        }
        return true;

    }


    /**
     * 增加实际库存(可用库存和实际库存都增加）
     * @return
     */
    public boolean casIncreaseActualStock(GoodsStockVO stockVO){
        GoodsStockVO goodsSumStockVO= this.queryIncreaseStock(stockVO,true);
        GoodsStockEntity goodsStockEntity= this.queryStockInfo(stockVO);
        if(goodsStockEntity!=null){
            goodsStockEntity.setBaseNum(goodsSumStockVO.getBaseNum());
            goodsStockEntity.setQtyNum(goodsSumStockVO.getQtyNum());
            goodsStockEntity.setAuxNum(goodsSumStockVO.getAuxNum());

            goodsStockEntity.setAvaBaseNum(goodsSumStockVO.getAvaBaseNum());
            goodsStockEntity.setAvaQtyNum(goodsSumStockVO.getAvaQtyNum());
            goodsStockEntity.setAvaAuxNum(goodsSumStockVO.getAvaAuxNum());

            this.updateById(goodsStockEntity);
        }else{
            GoodsEntity goodsEntity=goodsService.getById(stockVO.getGoodsId());
            goodsStockEntity=BeanConverter.convert(goodsEntity,GoodsStockEntity.class);
            goodsStockEntity.setBaseNum(goodsSumStockVO.getBaseNum());
            goodsStockEntity.setQtyNum(goodsSumStockVO.getQtyNum());
            goodsStockEntity.setAuxNum(goodsSumStockVO.getAvaAuxNum());

            goodsStockEntity.setAvaBaseNum(goodsSumStockVO.getAvaBaseNum());
            goodsStockEntity.setAvaQtyNum(goodsSumStockVO.getAvaQtyNum());
            goodsStockEntity.setAvaAuxNum(goodsSumStockVO.getAvaAuxNum());

            this.save(goodsStockEntity);
        }
        return true;
    }

    /**
     * 批量查询商品总库存数量
     */
    @Override
    public List<GoodsStockVO> batchQueryGoodsSaleNum(String[] goodsId) {
        return null;
    }
    /**
     * 查询单商品总库存数量
     */
    @Override
    public List<GoodsStockVO> queryGoodsSaleNum(String[] goodsId) {
        return null;
    }



    /***********************************************************************************************/
    /****************************************** 私有方法 ********************************************/
    /***********************************************************************************************/


    /**
     * 查询已使用库存
     * @param page
     */
    private void  converPageList(IPage<GoodsStockEntity> page){
        page.getRecords().forEach(e->{
            BigDecimal probNum=new BigDecimal("0");
            probHeadService.useProQty(e.getGoodsId());
            BigDecimal saleNum=orderHeadService.useSaleQty(e.getGoodsId());
            e.setAvaBaseNum(probNum.add(saleNum));
        });
    }
    /**
     * 获取查询条件
     *
     * @param
     */
    private QueryWrapper<GoodsStockEntity> getQueryWrapper(Map<String, Object> params) {
        QueryWrapper<GoodsStockEntity> queryWrapper=new QueryWrapper<>();
        if(!StrUtil.isEmptyIfStr(params.get("propKey"))){
            queryWrapper.and(wrapper -> wrapper);
        }


        if(!StrUtil.isBlankIfStr(params.get("goodsInfo"))){
            queryWrapper.likeLeft("goods_code",params.get("goodsInfo"));
            queryWrapper.or().likeLeft("goods_name",params.get("goodsInfo"));
        }

        if(!StrUtil.isBlankIfStr(params.get("warehouseCode"))){
            queryWrapper.eq("warehouse_code",params.get("warehouseCode"));
        }
        if(!StrUtil.isBlankIfStr(params.get("goodsCode"))){
            queryWrapper.eq("goods_code",params.get("goodsCode"));
        }
        queryWrapper.orderByAsc("goods_id,warehouse_id");
        return queryWrapper;
    }

    /**
     * 可询单个商品的可用库存和实际库存
     * @param invGoodsStockVO
     * @param isFlag
     * @return
     */
    private GoodsStockVO queryIncreaseStock(GoodsStockVO invGoodsStockVO,boolean isFlag){

        //期初
        GoodsAccountEntity goodsBeginAccount =goodsAccountService.queryGoodsBeginAccount(invGoodsStockVO);

        GoodsStockVO inGoodsStock=inLineService.queryInGoodsQty(invGoodsStockVO);

        GoodsStockVO outGoodsStock=outLineService.queryOutGoodsQty(invGoodsStockVO);


        if(goodsBeginAccount==null){
            goodsBeginAccount=new GoodsAccountEntity();
            goodsBeginAccount.setBeginBaseNum(BigDecimal.ZERO);
            goodsBeginAccount.setBeginQtyNum(BigDecimal.ZERO);
            goodsBeginAccount.setBeginAuxNum(BigDecimal.ZERO);
        }

        if(inGoodsStock==null){
            inGoodsStock=new GoodsStockVO();
            inGoodsStock.setBaseNum(BigDecimal.ZERO);
            inGoodsStock.setQtyNum(BigDecimal.ZERO);
            inGoodsStock.setAuxNum(BigDecimal.ZERO);
        }

        if(outGoodsStock==null){
            outGoodsStock=new GoodsStockVO();
            outGoodsStock.setBaseNum(BigDecimal.ZERO);
            outGoodsStock.setQtyNum(BigDecimal.ZERO);
            outGoodsStock.setAuxNum(BigDecimal.ZERO);
        }


        //实际库存
        invGoodsStockVO.setBaseNum(goodsBeginAccount.getBeginBaseNum().add(inGoodsStock.getBaseNum()).subtract(outGoodsStock.getBaseNum()));
        invGoodsStockVO.setAuxNum(goodsBeginAccount.getBeginAuxNum().add(inGoodsStock.getAuxNum()).subtract(outGoodsStock.getAuxNum()));
        invGoodsStockVO.setQtyNum(goodsBeginAccount.getBeginQtyNum().add(inGoodsStock.getQtyNum()).subtract(outGoodsStock.getQtyNum()));


        logger.info(" invGoodsStockVO JSON:{}", JSON.toJSONString(invGoodsStockVO));
        logger.info(" goodsBeginAccount JSON:{}", JSON.toJSONString(goodsBeginAccount));
        logger.info(" inGoodsStock JSON:{}", JSON.toJSONString(inGoodsStock));
        logger.info(" outGoodsStock JSON:{}", JSON.toJSONString(outGoodsStock));
        //增加可用库存查询
        invGoodsStockVO.setAvaBaseNum(goodsBeginAccount.getBeginAvaBaseNum().add(inGoodsStock.getBaseNum()).subtract(outGoodsStock.getBaseNum()));
        invGoodsStockVO.setAvaAuxNum(goodsBeginAccount.getBeginAvaAuxNum().add(inGoodsStock.getAuxNum()).subtract(outGoodsStock.getAuxNum()));
        invGoodsStockVO.setAvaQtyNum(goodsBeginAccount.getBeginAvaQtyNum().add(inGoodsStock.getQtyNum()).subtract(outGoodsStock.getQtyNum()));


        //增加
        if(isFlag){
            invGoodsStockVO.setBaseNum(invGoodsStockVO.getBaseNum().add(invGoodsStockVO.getBaseNum()));
            invGoodsStockVO.setAuxNum(invGoodsStockVO.getAuxNum().add(invGoodsStockVO.getAuxNum()));
            invGoodsStockVO.setQtyNum(invGoodsStockVO.getQtyNum().add(invGoodsStockVO.getQtyNum()));

            invGoodsStockVO.setAvaBaseNum(invGoodsStockVO.getAvaBaseNum().add(invGoodsStockVO.getBaseNum()));
            invGoodsStockVO.setAvaAuxNum(invGoodsStockVO.getAvaAuxNum().add(invGoodsStockVO.getAuxNum()));
            invGoodsStockVO.setAvaQtyNum(invGoodsStockVO.getAvaQtyNum().add(invGoodsStockVO.getQtyNum()));

        }else{
            invGoodsStockVO.setBaseNum(invGoodsStockVO.getBaseNum().subtract(invGoodsStockVO.getBaseNum()));
            invGoodsStockVO.setAuxNum(invGoodsStockVO.getAuxNum().subtract(invGoodsStockVO.getAuxNum()));
            invGoodsStockVO.setQtyNum(invGoodsStockVO.getQtyNum().subtract(invGoodsStockVO.getQtyNum()));

            invGoodsStockVO.setAvaBaseNum(invGoodsStockVO.getAvaBaseNum().subtract(invGoodsStockVO.getBaseNum()));
            invGoodsStockVO.setAvaAuxNum(invGoodsStockVO.getAvaAuxNum().subtract(invGoodsStockVO.getAuxNum()));
            invGoodsStockVO.setAvaQtyNum(invGoodsStockVO.getAvaQtyNum().subtract(invGoodsStockVO.getQtyNum()));
        }

        return invGoodsStockVO;
    }
}
